package apps;

import huffman.HuffmanModel;
import huffman.CodeParams;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DecimalFormat;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;

import bitstreams.BitInputStream;
import filetostring.TextFileToString;
import java.awt.Font;

public class Gui extends JFrame
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 5825403871734062734L;
	Double sizeBefore;
	Double sizeAfter;
	JTextPane textPane;
	JTextPane textPane_1;
	JTextArea textArea;
	JTextArea textArea_1;
	String path;
	String name;
	String text;
	File f;
	JLabel label;
	JLabel label_1;
	JLabel label_2;
	JLabel label_3;
	Boolean flag=false;		//if TRUE,use text file is set
	
	//IMPORTANT! LAST LETTER IN GIVEN ALPHABET WILL BE USED AS END OF INPUT!
	//char alphabet[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','\0'};
	//char alphabet[] = {'0','1','2','3','4','5','6','7','8','9','\0'};
	char alphabet[] = {'A','B','C','D','E','F','G','H','I','J'};
	public Gui() 
	{
		setResizable(false);//optional
		Image img = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/code2.png"));
		
		setIconImage(img);
		
		setTitle("Huffman Coding");
		getContentPane().setLayout(null);
		
		JPanel panel = new JPanel();
		panel.setBounds(0, 0, 634, 133);
		getContentPane().add(panel);
		panel.setLayout(null);
		
		ImageIcon icon = new ImageIcon(getClass().getResource("/Ok.png"));
	
		JButton btnBrowse = new JButton("Browse");
		btnBrowse.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
			}
		});
		btnBrowse.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				JFileChooser chooser = new JFileChooser();
			    chooser.setCurrentDirectory(new File("."));

			    chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
			      public boolean accept(File file) 
			      {
			        return file.getName().toLowerCase().endsWith(".txt")
			            || file.isDirectory();
			      }
			      public String getDescription() {
			        return "Text file";
			      }
			    });
			    int r = chooser.showOpenDialog(new JFrame());
			    if (r == JFileChooser.APPROVE_OPTION) {
			    	
			    name = chooser.getSelectedFile().getPath();
			    textPane.setText(name);
			    
			    f = new File(chooser.getSelectedFile().getPath());
			    TextFileToString temp = new TextFileToString(f);
			    sizeBefore=new Double(f.length());
			    System.out.println(sizeBefore);
				label_1.setText(Long.toString(f.length())+"byte");
				//temp contains text of input file,show it in text area
			    textArea.setText(temp.getStr());
			    //text file was selected
			    flag=true;
			    }
			}
		});
		btnBrowse.setBounds(503, 13, 97, 25);
		panel.add(btnBrowse);
		
		textPane = new JTextPane();
		textPane.setFont(new Font("Tahoma", Font.PLAIN, 14));
		textPane.setEditable(false);
		textPane.setBounds(126, 16, 365, 22);
		panel.add(textPane);
		
		JLabel lblSelectTextFile = new JLabel("Select text file");
		lblSelectTextFile.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblSelectTextFile.setBounds(12, 22, 102, 16);
		panel.add(lblSelectTextFile);
		
		//Encode
		JButton btnEncode = new JButton("Encode");
		btnEncode.addMouseListener(new MouseAdapter() 
		{
			@Override
			public void mouseClicked(MouseEvent arg0) //encode button clicked
			{	
				//text file selected
				if(flag==true)
				{
				HuffmanModel model = new HuffmanModel(alphabet);
				try 
				{
					model.encode(new FileInputStream(f), 
							 new FileOutputStream(getFilePath()+"compressed.bin"));
					model.reset();
					
					model.decode(new FileInputStream(getFilePath()+"compressed.bin"), 
							 new FileOutputStream(getFilePath()+"decompressed.txt") );
					
					model.reset();
					createOutputFiles(model, new FileInputStream(getFilePath()+"compressed.bin"), 
											 new FileOutputStream(getFilePath()+"compressed.txt") );
					label.setVisible(true);
					
					//show compressed text
					TextFileToString temp = new TextFileToString(new File(getFilePath()+"compressed.txt"));
					textArea_1.setText(temp.getStr());
					//compressed binary file size
					sizeAfter=new Double(new File(getFilePath()+"compressed.bin").length());
					
					label_2.setText(Long.toString(new File(getFilePath()+"compressed.bin").length())+"byte");
					double res = (sizeAfter/sizeBefore)*100;
					
					label_3.setText(new DecimalFormat("##.##").format(res)+"%");
					flag=false;
				} 
				catch (FileNotFoundException e) {e.printStackTrace();} 
				catch (IOException e) {e.printStackTrace();}
				}
				//text file wasn't selected
				else
				{
					String message = "Nothing to encode!!!\n" +
							"Select input text file.";
					    JOptionPane.showMessageDialog(new JFrame(), message, "Error",
					        JOptionPane.ERROR_MESSAGE);
				}
			}
			
			
		});
		btnEncode.setBounds(503, 51, 97, 25);
		panel.add(btnEncode);
		
		label = new JLabel(icon);
		//label = new JLabel("");
		label.setBounds(527, 82, 48, 48);
		panel.add(label);
		
		JButton btnClear = new JButton("Clear");
		btnClear.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) //clear all fields
			{
				textArea.setText("");
				textArea_1.setText("");
				textPane.setText("");
				label_3.setText("");
				label_2.setText("");
				label_1.setText("");
				label.setVisible(false);
			}
		});
		
		btnClear.setBounds(349, 89, 97, 25);
		panel.add(btnClear);
		label.setVisible(false);
		JPanel panel_1 = new JPanel();
		panel_1.setBounds(0, 134, 634, 452);
		getContentPane().add(panel_1);
		panel_1.setLayout(null);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		scrollPane.setBounds(12, 24, 622, 421);
		panel_1.add(scrollPane);
		
		textArea = new JTextArea();
		textArea.setLineWrap(true);
		scrollPane.setViewportView(textArea);
		
		JLabel lblInputText = new JLabel("Input Text:");
		lblInputText.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblInputText.setBounds(12, 0, 77, 29);
		panel_1.add(lblInputText);
		
		JPanel panel_2 = new JPanel();
		panel_2.setBounds(646, 134, 634, 452);
		getContentPane().add(panel_2);
		panel_2.setLayout(null);
		
		JScrollPane scrollPane_1 = new JScrollPane();
		scrollPane_1.setBounds(0, 24, 634, 420);
		scrollPane_1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane_1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		panel_2.add(scrollPane_1);
		
		textArea_1 = new JTextArea();
		textArea_1.setLineWrap(true);
		scrollPane_1.setViewportView(textArea_1);
		
		JLabel lblCompressedText = new JLabel("Compressed text:");
		lblCompressedText.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblCompressedText.setBounds(0, 0, 124, 29);
		panel_2.add(lblCompressedText);
		
		JPanel panel_3 = new JPanel();
		panel_3.setBounds(646, 13, 634, 120);
		getContentPane().add(panel_3);
		panel_3.setLayout(null);
		
		JLabel lblStatistics = new JLabel("Statistics");
		lblStatistics.setBounds(0, 0, 72, 24);
		panel_3.add(lblStatistics);
		lblStatistics.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		JLabel lblInputFileSize = new JLabel("Input file size:");
		lblInputFileSize.setBounds(0, 26, 95, 16);
		panel_3.add(lblInputFileSize);
		lblInputFileSize.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		JLabel lblBinaryFileSize = new JLabel("Binary file size:");
		lblBinaryFileSize.setBounds(0, 48, 95, 16);
		panel_3.add(lblBinaryFileSize);
		lblBinaryFileSize.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		label_1 = new JLabel("");
		label_1.setBounds(135, 26, 72, 16);
		panel_3.add(label_1);
		label_1.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		label_2 = new JLabel("");
		label_2.setBounds(135, 48, 72, 16);
		panel_3.add(label_2);
		label_2.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		JLabel lblAlphabet = new JLabel("Alphabet used:");
		lblAlphabet.setBounds(0, 101, 112, 16);
		panel_3.add(lblAlphabet);
		lblAlphabet.setFont(new Font("Tahoma", Font.PLAIN, 14));
		
		textPane_1 = new JTextPane();
		textPane_1.setBounds(135, 93, 258, 24);
		panel_3.add(textPane_1);
		textPane_1.setFont(new Font("Tahoma", Font.PLAIN, 14));
		textPane_1.setEditable(false);
		
		String alph = new String(alphabet);
		textPane_1.setText(alph);
		
		JLabel lblCompressionRatio = new JLabel("Compression ratio:");
		lblCompressionRatio.setFont(new Font("Tahoma", Font.PLAIN, 14));
		lblCompressionRatio.setBounds(0, 72, 126, 16);
		panel_3.add(lblCompressionRatio);
		
		label_3 = new JLabel("");
		label_3.setFont(new Font("Tahoma", Font.PLAIN, 14));
		label_3.setBounds(135, 72, 72, 16);
		panel_3.add(label_3);
		
	}
	public String getFilePath()//get parent directory
	{
		String path;
		path=f.getParent()+"/";
		
		return path;
	}
	public void createOutputFiles( HuffmanModel model, InputStream inStream, OutputStream outStream )
	{
		BitInputStream input = new BitInputStream(inStream);
		PrintWriter outWriter = new PrintWriter(new OutputStreamWriter(outStream));
		
		try 
		{

			int c = 0;
			while( (c = input.read(1)) != -1 )
			{
				outWriter.write(Integer.toBinaryString(c));
			}
			input.close();
			outWriter.close();
			
		} 
		catch (IOException e) {e.printStackTrace();}
	}
}
